<?php
require_once("arc/ARC2.php");

class LinkedData {
    private $prefixes = array(
        "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
        "rdfs" => "http://www.w3.org/2000/01/rdf-schema#",
        "foaf" => "http://xmlns.com/foaf/0.1/",
        "mo" => "http://purl.org/ontology/mo/",
        "skos" => "http://www.w3.org/2004/02/skos/core#",
        "bio" => "http://purl.org/vocab/bio/0.1/",
        "mn" => "http://musicnet.mspace.fm/ontology#",
        "owl" => "http://www.w3.org/2002/07/owl#",
    );

    private $rdfheader = ""; # init in constructor

    private $config;

    function __construct(){
        $this->config = $this->loadConfig();
        $this->xml = simplexml_load_file($this->config['source']);
        $this->webdata = $this->get_web_links();
        $this->rdfheader = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns:rdf      = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:rdfs     = "http://www.w3.org/2000/01/rdf-schema#"
         xmlns:foaf     = "http://xmlns.com/foaf/0.1/"
         xmlns:mo       = "http://purl.org/ontology/mo/"
         xmlns:skos     = "http://www.w3.org/2004/02/skos/core#"
         xmlns:bio      = "http://purl.org/vocab/bio/0.1/"
         xmlns:mn       = "http://musicnet.mspace.fm/ontology#"
         xmlns:owl      = "http://www.w3.org/2002/07/owl#"
>

EOF;
    }

    function loadConfig(){
        $config = array();
        require("config.php"); // overwrites $config
        return $config;
    }

    function get_url_data($url, $header){
        $dir = "cached_bbc";
        $md5 = md5($url);
        $cache_file = "$dir/$md5";
        if (file_exists($cache_file)){
            return file_get_contents($cache_file);
        } else {
            #$urldata = file_get_contents($url);
            sleep(1); # be nice to the beeb

            $process = curl_init($url);
            #curl_setopt($process, CURLOPT_HTTPHEADER, array("Accept: application/rdf+xml"));
            curl_setopt($process, CURLOPT_HTTPHEADER, $header);
            curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); 
            $urldata = curl_exec($process);
            curl_close($process);

            file_put_contents($cache_file, $urldata);
            return $urldata;
        }
    }

    function deref_harvest($uri){
        $urldata = $this->get_url_data($uri, array("Accept: application/rdf+xml"));

        $parser = ARC2::getRDFParser();
        $parser->parse($uri, $urldata);
        $index = $parser->getSimpleIndex();

        $derefdata = array();
        foreach ($this->config['predicates'] as $def){
            $predicate = $def['predicate'];
            $catalog = $def['catalog'];
            $type = $def['type'];

            if (array_key_exists($uri, $index) and array_key_exists($predicate, $index[$uri])){
                foreach ($index[$uri][$predicate] as $value){

                    if ($catalog === "sameas" || $catalog === "biography"){
                        foreach (array_keys($this->config['urlmatch']) as $urlstart){
                            if (strpos($value, $urlstart) === 0){
                                $catalog = $this->config['urlmatch'][$urlstart];
                            }
                        }
                    }

                    $datadef = array("catalog" => $catalog, "type" => $type, "value" => $value);
                    if ($type === "variant"){
                        $datadef['url'] = $uri;
                    }
                    if (array_key_exists('sameas', $def)){
                        $datadef['sameas'] = $def['sameas'];
                    }

                    $derefdata[] = $datadef;
                }
            }

        }
        return $derefdata;
    }

    function get_web_links(){
        $mblinks = $this->get_musicbrainz_urls();

        // process the bbc data to find the musicbrainz links and the corresponding BBC urls
        $xml = simplexml_load_string($this->get_url_data($this->config['bbcquery'], array()));
        $map = array();
        foreach ($xml->results->result as $result){
            $bbc = "";
            $mb = "";
            foreach ($result->binding as $binding){
                $name = $binding['name']."";
                if ($name == "x"){
                    # subject (bbc uri)
                    $bbc = $binding->uri . "";
                } else {
                    # musicbrainz url
                    $mb = $binding->uri . "";
                }
            }
            if (! (strpos($bbc, "http://api.talis.com") === 0)){ # skip talis internal (b-node?) URIs
                $map[$mb][] = $bbc;
            }
        }

        $bbcdata = array();

        // loop through musicbrainz links from the latest XML dump and process the bbc files
        foreach (array_keys($mblinks) as $mb){
            $id = $mb; # musicnet id
            foreach ($mblinks[$mb] as $mburl){
                if (array_key_exists($mburl, $map)){
                    $bbcurls = $map[$mburl];
                    foreach ($bbcurls as $bbcurl){
                        $derefdata = $this->deref_harvest($bbcurl);
                        foreach ($derefdata as $row){
                            $bbcdata[$mburl][] = $row;
                        }
                    }
                }
            }
        }

        // loop through all dbpedia entries, deref, cache and insert offsite links
        foreach (array_keys($bbcdata) as $mburl){
            $list = $bbcdata[$mburl];
            foreach ($list as $variant){
                if ($variant['catalog'] === 'dbpedia'){
                    $derefdata = $this->deref_harvest($variant['value']);
                    foreach ($derefdata as $row){
                        print_r($row);
                        $bbcdata[$mburl][] = $row;
                    }
                }
            }
        }


        print_r($bbcdata);

        return $bbcdata;
    }

    function escape($in){
        return preg_replace("/[&]/","&amp;",$in);
    }

    function get_musicbrainz_urls(){
        $urls = array();
        foreach ($this->xml->person as $person){
            $id = $person['musicnetid'] . "";
            if ($person->namevariants && $person->namevariants->variant){
                foreach ($person->namevariants->variant as $altname){
                    $url = $altname['url'] . "";
                    $catalog = $altname['catalog'] . "";
                    if ($catalog == "musicbrainz"){
                        $urls[$id][] = $url;
                    }
                }
            }
        }
        return $urls;
    }

    function generate(){
        $uris = array();
        $files = array();
        foreach ($this->xml->person as $person){
            $id = $person['musicnetid'];

            $outfile = $this->config['output_dir'] . "/" . $id . ".rdf";
            $uri = $this->make_rdf_file($outfile, $person);
            $uris[] = $uri;
            $files[] = $outfile;
        }
        file_put_contents($this->config['output_list'], implode("\n",$uris));
        $this->generate_void($uris);
        $this->generate_dump($files);
    }

    function generate_dump($files){
        $dump = $this->rdfheader;
        foreach ($files as $file){
            $rdf = file_get_contents($file);
            $rdf = preg_replace("/^.*<!-- startdata -->/s", "", $rdf);
            $rdf = preg_replace("/<!-- enddata -->.*$/s", "", $rdf);
            $dump .= "\n$rdf\n";
        }
        $dump .= "</rdf:RDF>\n";
        file_put_contents($this->config['output_dump'], $dump);
    }

    function generate_void($uris){
        $voidfile = $this->config['output_void'];

        $uris_n3 = "";
        foreach ($uris as $uri){
# void:exampleResource <http://musicnet.mspace.fm/person/8c0ac965728ecdfe647439593046e683#id> ;
            $uris_n3 .= " void:exampleResource <$uri> ;\n";
        }
    
        $void = <<<EOF
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix void: <http://rdfs.org/ns/void#> .
@prefix : <#> .

## your dataset
<http://musicnet.mspace.fm/void#> rdf:type void:Dataset ;
 foaf:homepage <http://musicnet.mspace.fm/> ;
 dcterms:title "MusicNet" ;
 dcterms:description "MusicNet produces and publishes linked data about classical music composers using data from publishers partnering on the musicSpace project. This data will be exposed using existing linked data technology and will form the basis of an online source of canonical data about (and, in time, comprehensive index of) musical composers. It is intended that as well as exposing basic meta- data about each composer (for example birth/death date and nationality) the linked data will provide URLs that reference back into the online web catalogues of our data partners so that musicologists can immediately access all relevant data from each partner collection." ;
$uris_n3
 void:subset :myDS-DS1 .

## datasets you link to

# interlinking to :DS1
:DS1 rdf:type void:Dataset ;
 foaf:homepage <http://bbc.co.uk/music/> ;
 dcterms:title "BBC /music" ;
 dcterms:description "Music data at the British Broadcasting Corporation." ; 
 void:exampleResource <http://bbc.co.uk/music/artists/f91e3a88-24ee-4563-8963-fab73d2765ed#artist> .

:myDS-DS1 rdf:type void:Linkset ;
 void:linkPredicate <http://www.w3.org/2002/07/owl#sameAs> ;
 void:target <http://musicnet.mspace.fm/void#> ;
 void:target :DS1 .
EOF;
        file_put_contents($voidfile, $void);

    }

    function make_rdf_file($outfile, $person){
        $id = $person['musicnetid'];
        $uribase = $this->config['ns'] . $id;
        # uri of the person is: $uribase#id

        # url of the rdf is: $uribase.rdf
        # url of the html is: $uribase.html
        # conneg url is: $uribase (302s to the above, a la bbc)

        $label = $person->label;

        $otherdata = "";

        $artistdates = "";
        if ($person->birthdate && $person->birthdate != ""){
            $birthdate = $person->birthdate;
            $artistdates .= <<<EOF
  <bio:event>
    <bio:Birth>
      <bio:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">$birthdate</bio:date>
    </bio:Birth>
  </bio:event>


EOF;
        }
        if ($person->deathdate && $person->deathdate != ""){
            $deathdate = $person->deathdate;
            $artistdates .= <<<EOF
  <bio:event>
    <bio:Death>
      <bio:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">$deathdate</bio:date>
    </bio:Death>
  </bio:event>


EOF;
        }

        $altlabels = "";
        if ($person->namevariants && $person->namevariants->variant){
            foreach ($person->namevariants->variant as $altname){
                $url = $this->escape($altname['url']."");
                $catalog = $altname['catalog']."";
                $catalog_name = $this->config['catalog_map'][$catalog];
                $otherURI = "$uribase#$catalog";

                if ($catalog == "musicbrainz"){
                    $altlabels .= <<<EOF
  <mo:musicbrainz rdf:resource="$url" />


EOF;
                    if (array_key_exists($url, $this->webdata)){
                        $webdatas = $this->webdata[$url];
                        foreach ($webdatas as $webdata){
                            $wd_catalog = $webdata['catalog'];
                            $wd_type = $webdata['type'];
                            $wd_value = $this->escape($webdata['value']);

                            if ($wd_type === "variant"){
                                $wd_url = $this->escape($webdata['url']);
                                $altlabels .= <<<EOF
  <skos:altLabel>$wd_value</skos:altLabel>
  <foaf:page rdf:resource="$wd_url" />
  <owl:sameAs rdf:resource="$wd_url" />

EOF;

                            } else if ($wd_type === "image"){
                                $altlabels .= <<<EOF
  <foaf:depiction rdf:resource="$wd_value" />


EOF;
                            } else if ($wd_type === "link"){
                                $altlabels .= <<<EOF
  <foaf:page rdf:resource="$wd_value" />

EOF;

                                if (array_key_exists('sameas', $webdata) && $webdata['sameas']){
                                    $altlabels .= <<<EOF
  <owl:sameAs rdf:resource="$wd_value" />


EOF;
                                }
                            } else {
                                throw new Exception("Unknown web data type \"$wd_type\"");
                            }
                        }

                    }
                }

                $altlabels .= <<<EOF
  <skos:altLabel>$altname</skos:altLabel>
  <foaf:page rdf:resource="$url" />
  <owl:sameAs rdf:resource="$otherURI" />


EOF;
                $otherdata .= <<<EOF

<mo:MusicArtist rdf:about="$otherURI">
  <rdf:type rdf:resource="http://purl.org/ontology/mo/SoloMusicArtist" />
  <foaf:name>$altname</foaf:name>
  <rdfs:label>$altname</rdfs:label>

  <rdfs:isDefinedBy rdf:resource="http://musicnet.mspace.fm/ontology#$catalog" />
  
  <foaf:isPrimaryTopicOf rdf:resource="$url" />
</mo:MusicArtist>


EOF;


            }
        }

        $rdf = $this->rdfheader;
        $rdf .= <<<EOF
<!-- startdata -->

<rdf:Description rdf:about="$uribase.rdf">
  <rdfs:label>Description of the artist $label</rdfs:label>
  <foaf:primaryTopic rdf:resource="$uribase#id"/>
</rdf:Description>

<mo:MusicArtist rdf:about="$uribase#id">
  <rdf:type rdf:resource="http://purl.org/ontology/mo/SoloMusicArtist" />
  <foaf:name>$label</foaf:name>
  
$artistdates

  <foaf:page rdf:resource="$uribase.html" />

$altlabels

</mo:MusicArtist>

$otherdata

<!-- enddata -->
</rdf:RDF>

EOF;
        file_put_contents($outfile, $rdf);
        return "$uribase#id";
    }

}
?>
